/*
    Copyright (C) 2009-2011 DeSmuME Team

    This file is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    This file is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with the this software.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _FIRMWARE_H_
#define _FIRMWARE_H_
#include "common.h"

// the count of bytes copied from the firmware into memory
#define NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT 0x70

#define FW_CONFIG_FILE_EXT "dfc"

class CFIRMWARE
{
private:
    u8      *tmp_data9;
    u8      *tmp_data7;
    u32     size9, size7;

    u32     keyBuf[0x412];
    u32     keyCode[3];

    bool    getKeyBuf();
    void    crypt64BitUp(u32 *ptr);
    void    crypt64BitDown(u32 *ptr);
    void    applyKeycode(u32 modulo);
    bool    initKeycode(u32 idCode, int level, u32 modulo);
    u16     getBootCodeCRC16();
    u32     decrypt(const u8 *in, u8* &out);
    u32     decompress(const u8 *in, u8* &out);

public:
    CFIRMWARE(): size9(0), size7(0), ARM9bootAddr(0), ARM7bootAddr(0), patched(0) {};

    bool load();

    static std::string GetExternalFilePath();

    struct HEADER {
        u16 part3_rom_gui9_addr;        // 000h
        u16 part4_rom_wifi7_addr;       // 002h
        u16 part34_gui_wifi_crc16;      // 004h
        u16 part12_boot_crc16;          // 006h
        u8  fw_identifier[4];           // 008h
        u16 part1_rom_boot9_addr;       // 00Ch
        u16 part1_ram_boot9_addr;       // 00Eh
        u16 part2_rom_boot7_addr;       // 010h
        u16 part2_ram_boot7_addr;       // 012h
        u16 shift_amounts;              // 014h
        u16 part5_data_gfx_addr;        // 016h

        u8  fw_timestamp[5];            // 018h
        u8  console_type;               // 01Dh
        u16 unused1;                    // 01Eh
        u16 user_settings_offset;       // 020h
        u16 unknown1;                   // 022h
        u16 unknown2;                   // 024h
        u16 part5_crc16;                // 026h
        u16 unused2;                    // 028h - FFh filled
    } header;

    u32     ARM9bootAddr;
    u32     ARM7bootAddr;
    bool    patched;
};

int copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data);
int NDS_CreateDummyFirmware( struct NDS_fw_config_data *user_settings);
void NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config);
void NDS_PatchFirmwareMAC();

#endif

